//
//  ZSerializeCommonPrivate.h
//  Part of Z-Way.C library
//
//  Created by Serguei Poltorak on 08.10.2024.
//
//  Copyright (c) 2024 Z-Wave.Me
//  All rights reserved
//  info@z-wave.me
//
//  This source file is subject to the terms and conditions of the
//  Z-Wave.Me Software License Agreement which restricts the manner
//  in which it may be used.
//

#ifndef zserialize_common_private_h
#define zserialize_common_private_h

#include "ZPlatform.h"
#include "ZData.h"
#include "ZByteOperations.h"
#include "ZStreamPrivate.h"

#include <float.h>

typedef void _ZSerializeCommonRootObject;
typedef ZWBYTE *_ZSerializeCommonCommandClassesList;
typedef ZWBYTE *_ZSerializeCommonInstancesList;
typedef ZWWORD _ZSerializeCommonNODE;
typedef _ZSerializeCommonNODE *_ZSerializeCommonDevicesList;

typedef struct _ZSerializeCommonSettings_s
{
    ZWError (*write)(void *args, void *data, size_t length);
    void *args;
    size_t json_block_size;
} _ZSerializeCommonSettings_t;

typedef struct _ZSerializeCommonRootObjectHandler_s
{
    ZDataHolder (*find_controller_data)(const _ZSerializeCommonRootObject *root_object, ZWCSTR path);
    ZDataHolder (*find_device_instance_cc_data)(const _ZSerializeCommonRootObject *root_object, _ZSerializeCommonNODE device_id, ZWBYTE instance_id, ZWBYTE cc_id, ZWCSTR path);
    const ZWCHAR *(*get_command_class_name)(ZWBYTE cc_id);
    _ZSerializeCommonCommandClassesList (*command_classes_list)(const _ZSerializeCommonRootObject *root_object, _ZSerializeCommonNODE deviceId, ZWBYTE instanceId);
    void (*command_classes_list_free)(_ZSerializeCommonCommandClassesList list);
    ZDataHolder (*find_device_instance_data)(const _ZSerializeCommonRootObject *root_object, _ZSerializeCommonNODE device_id, ZWBYTE instance_id, ZWCSTR path);
    time_t (*get_commands_update_time)(const _ZSerializeCommonRootObject *root_object, _ZSerializeCommonNODE node_id, ZWBYTE instance_id);
    _ZSerializeCommonInstancesList (*instances_list)(const _ZSerializeCommonRootObject *root_object, _ZSerializeCommonNODE deviceId);
    void (*instances_list_free)(_ZSerializeCommonInstancesList list);
    ZDataHolder (*find_device_data)(const _ZSerializeCommonRootObject *root_object, _ZSerializeCommonNODE device_id, ZWCSTR path);
    time_t (*get_instances_update_time)(const _ZSerializeCommonRootObject *root_object, _ZSerializeCommonNODE node_id);
    _ZSerializeCommonDevicesList (*devices_list)(const _ZSerializeCommonRootObject *root_object);
    time_t (*get_devices_update_time)(const _ZSerializeCommonRootObject *root_object);
    void (*devices_list_free)(_ZSerializeCommonDevicesList list);
} _ZSerializeCommonRootObjectHandler_t;

typedef struct _ZSerializeCommonCtx_s
{
    _ZSerializeCommonRootObject *root_object;
    const _ZSerializeCommonRootObjectHandler_t *root_object_handler;
    const _ZStreamWriter_t *writer;
    void *ctx_writer;
    ZWCHAR buffer_for_printf[MAX(Z_SIZE_MEMORY_FOR_PRINTF_NUMBER(ZWDWORD64), (FLT_MAX_10_EXP + 6 + 1 + 1 + 1 + 1) * sizeof(ZWCHAR))]; // 6 - fractional; 1 - zero; 1 - point; 1 + sign; 1 - one significant number
    ZWBOOL empty;
} _ZSerializeCommonCtx_t;

static inline _ZSerializeCommonRootObject *_zserialize_common_get_root_object(_ZSerializeCommonCtx_t *ctx)
{
    return ctx->root_object;
};

static inline void _zserialize_common_init(_ZSerializeCommonCtx_t *const ctx, _ZSerializeCommonRootObject *root_object, const _ZSerializeCommonRootObjectHandler_t *const root_object_handler, const _ZStreamWriter_t *const writer, void *const ctx_writer)
{
    ctx->root_object = root_object;
    ctx->root_object_handler = root_object_handler;
    ctx->writer = writer;
    ctx->ctx_writer = ctx_writer;
    ctx->empty = TRUE;
}
static inline void _zserialize_common_free(_ZSerializeCommonCtx_t *const UNUSED(ctx))
{
}
static inline ZWBOOL _zserialize_common_is_empty(_ZSerializeCommonCtx_t *const ctx)
{
    return ctx->empty;
}
ZWEXPORT_PRIVATE ZWError _zserialize_common_tree(_ZSerializeCommonCtx_t *const ctx, const time_t timestamp);
ZWEXPORT_PRIVATE ZWError _zserialize_common_stub(_ZSerializeCommonCtx_t *const ctx, const ZWCSTR str);
ZWEXPORT_PRIVATE ZWError _zserialize_common_int(_ZSerializeCommonCtx_t *const ctx, const int n);
static inline ZWError _zserialize_common_boolean(_ZSerializeCommonCtx_t *const ctx, const ZWBOOL value)
{
    return _zserialize_common_stub(ctx, value ? "true" : "false");
}
ZWEXPORT_PRIVATE ZWError _zserialize_common_dh(_ZSerializeCommonCtx_t *const ctx, const ZDataHolder data);
ZWEXPORT_PRIVATE ZWError _zserialize_common_dh_value(_ZSerializeCommonCtx_t *const ctx, const ZDataHolder data);
ZWEXPORT_PRIVATE ZWError _zserialize_common_string(_ZSerializeCommonCtx_t *const ctx, const ZWCSTR str, const size_t length);
ZWEXPORT_PRIVATE ZWError _zserialize_common_string_escape(_ZSerializeCommonCtx_t *const ctx, const ZWCSTR str);
ZWEXPORT_PRIVATE ZWError _zserialize_common_float(_ZSerializeCommonCtx_t *const ctx, const float n);
ZWEXPORT_PRIVATE ZWError _zserialize_common_int(_ZSerializeCommonCtx_t *const ctx, const int n);
ZWEXPORT_PRIVATE ZWError _zserialize_common_ptr(_ZSerializeCommonCtx_t *const ctx, const void *const ptr);

ZWEXPORT_PRIVATE ZWError _zserialize_common_parse_to_string(_ZSerializeCommonRootObject *const root_object, const _ZSerializeCommonRootObjectHandler_t *const root_object_handler, const ZWBOOL is_string, _ZByteData_t *const data, void *const arg, ZWError (*const callback)(_ZSerializeCommonCtx_t *, void *));

#endif // zserialize_common_private_h